﻿using System;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using NETCONLib;
using WirelessAccessPoint.InteropServices;

namespace WirelessAccessPoint.Core
{
    public static class Extensions
    {
        /// <summary>
        /// DOT11_MAC_ADDRESS構造体をMACアドレス文字列表現に変換します。
        /// </summary>
        /// <param name="dot11MacAddress">
        /// DOT11_MAC_ADDRESS構造体。
        /// </param>
        /// <returns>
        /// MACアドレス文字列表現。
        /// </returns>
        public static string ToStringMacAddress(this DOT11_MAC_ADDRESS dot11MacAddress)
        {
            return string.Join("-", dot11MacAddress.ucDot11MacAddress.Select(b => b.ToString("X2")));
        }

        /// <summary>
        /// バイト配列をMACアドレス文字列表現に変換します。
        /// </summary>
        /// <param name="byteArray">
        /// バイト配列。
        /// </param>
        /// <param name="length">
        /// バイト配列の先頭何バイトを使用するか。
        /// </param>
        /// <returns>
        /// MACアドレス文字列表現。
        /// </returns>
        public static string ToStringMacAddress(this byte[] byteArray, int length)
        {
            return string.Join("-", byteArray.Take(length).Select(b => b.ToString("X2")));
        }

        /// <summary>
        /// ポインタを型Tの構造体へ変換します。
        /// </summary>
        /// <typeparam name="T">
        /// 変換する構造体の型。
        /// </typeparam>
        /// <param name="pointer">
        /// 構造体へ変換するポインタ。
        /// </param>
        /// <returns>
        /// 型Tの構造体。
        /// </returns>
        public static T ToStructure<T>(this IntPtr pointer)
        {
            return (T) Marshal.PtrToStructure(pointer, typeof(T));
        }

        /// <summary>
        /// 列挙値をラベル文字列へ変換します。
        /// </summary>
        /// <typeparam name="T">
        /// ラベル文字列を取得するリソースの型。
        /// </typeparam>
        /// <param name="value">
        /// ラベル文字列へ変換する列挙値。
        /// </param>
        /// <returns>
        /// ラベル文字列。
        /// </returns>
        public static string ToLabel<T>(this Enum value)
        {
            if (value == null)
            {
                return string.Empty;
            }
            else
            {
                var property = typeof(T).GetProperty(value.ToString(), BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
                return property == null ? value.ToString() : property.GetValue(typeof(T), null) as string;
            }
        }

        /// <summary>
        /// 指定したCOMオブジェクトの参照カウントをデクリメントします。
        /// </summary>
        /// <param name="o">
        /// COMオブジェクト。
        /// </param>
        public static void ReleaseComObject(this INetSharingConfiguration o)
        {
            if (o != null)
            {
                Marshal.ReleaseComObject(o);
            }
        }

        /// <summary>
        /// 指定したCOMオブジェクトの参照カウントをデクリメントします。
        /// </summary>
        /// <param name="o">
        /// COMオブジェクト。
        /// </param>
        public static void ReleaseComObject(this INetConnectionProps o)
        {
            if (o != null)
            {
                Marshal.ReleaseComObject(o);
            }
        }

        /// <summary>
        /// 指定したCOMオブジェクトの参照カウントをデクリメントします。
        /// </summary>
        /// <param name="o">
        /// COMオブジェクト。
        /// </param>
        public static void ReleaseComObject(this INetConnection o)
        {
            if (o != null)
            {
                Marshal.ReleaseComObject(o);
            }
        }

        /// <summary>
        /// 指定したCOMオブジェクトの参照カウントをデクリメントします。
        /// </summary>
        /// <param name="o">
        /// COMオブジェクト。
        /// </param>
        public static void ReleaseComObject(this INetSharingEveryConnectionCollection o)
        {
            if (o != null)
            {
                Marshal.ReleaseComObject(o);
            }
        }

        /// <summary>
        /// 指定したCOMオブジェクトの参照カウントをデクリメントします。
        /// </summary>
        /// <param name="o">
        /// COMオブジェクト。
        /// </param>
        public static void ReleaseComObject(this NetSharingManager o)
        {
            if (o != null)
            {
                Marshal.ReleaseComObject(o);
            }
        }
    }
}
